package com.glsc.ngateway.platform.service.cmdb;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.base.domain.mysql.cmdb.CmdbChangeLog;
import com.glsc.ngateway.common.base.domain.mysql.cmdb.CmdbDeviceDetail;
import com.glsc.ngateway.common.base.domain.mysql.cmdb.CmdbMemoryDetail;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.cmdb.FlowFormPartIn;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.cmdb.CmdbChangeLogRepository;
import com.glsc.ngateway.common.base.repo.mysql.cmdb.CmdbMemoryDetailRepository;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.flow.cmdb.FlowFormPartInRepo;
import com.glsc.ngateway.platform.utils.SpecificationUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.glsc.ngateway.common.api.common.enums.DictConstant.*;

@Service
public class CmdbMemoryDetailService {

    @Autowired
    private SequenceProductService sequenceProductService;
    @Autowired
    private CmdbMemoryDetailRepository cmdbMemoryDetailRepository;
    @Autowired
    private CmdbChangeLogRepository cmdbChangeLogRepository;
    @Autowired
    private FlowFormPartInRepo flowFormPartInRepo;

    public Object search(String type, Object paramsObj) {
        JSONObject objParmams = JSONObject.parseObject(JSONObject.toJSONString(paramsObj)).entrySet().stream()
                .filter(entry -> !entry.getValue().toString().isEmpty())
                .collect(JSONObject::new, (obj, entry) -> obj.put(entry.getKey(), entry.getValue()), JSONObject::putAll);

        if (StrUtil.isEmpty(objParmams.getString("orderByDirection"))){
            objParmams.put("orderByDirection","DESC");
        }
        if (StrUtil.isEmpty(objParmams.getString("orderByField"))){
            objParmams.put("orderByField","id");
        }
        Sort sort = Sort.by(Sort.Direction.fromString(objParmams.getString("orderByDirection")), objParmams.getString("orderByField"));

        Pageable pageable = PageRequest.of(objParmams.getInteger("pageNo")- 1, objParmams.getInteger("pageSize"),sort);

        if (CMDB_MEMORY_DETAIL.equals(type)){
            CmdbMemoryDetail paramSearchDto = JSONObject.parseObject(JSONObject.toJSONString(objParmams),CmdbMemoryDetail.class);
            Page<CmdbMemoryDetail> result = cmdbMemoryDetailRepository.searchByParam(pageable,paramSearchDto);
            result.getContent().forEach(e -> {
                if (e.getCmdbMemoryStandard() != null){
                    e.setPartNum(e.getCmdbMemoryStandard().getPartNum());
                }
            });
            return  result;
        }


        return null;
    }

    /**
     * @param cmdbMemoryDetail
     * @param account          操作人员
     * @param cmdbConfirm
     */
    public CmdbMemoryDetail addOrUpdateMemoryDetail(CmdbMemoryDetail cmdbMemoryDetail, String account, String cmdbConfirm) {
        int addOrUpdateFlag = 0;
        cmdbMemoryDetail.setIsDelete(NO_DELETE);
        CmdbChangeLog log = new CmdbChangeLog();
        if (cmdbMemoryDetail.getMemoryDetailId() != null){
            //修改
            log.setChangeType(DictConstant.UPDATE_STRING);
            addOrUpdateFlag = 2;
        } else {
            //新增
            log.setChangeType(DictConstant.ADD_STRING);
            //自动生成编号
            String code = sequenceProductService.buildSequence(CMDB_MEMORY_DETAIL);
            cmdbMemoryDetail.setMemoryDetailCode(code);
            addOrUpdateFlag = 1;
        }
        if (addOrUpdateFlag != 0){
            checkUnique(cmdbMemoryDetail,addOrUpdateFlag,cmdbConfirm);
        }
        log.setChangeContent(JSONObject.toJSONString(cmdbMemoryDetail));
        log.setChangeFrom(CMDB_MEMORY_DETAIL);
        log.setChangeId(cmdbMemoryDetail.getMemoryDetailId() != null ? cmdbMemoryDetail.getMemoryDetailId().toString() : null);
        log.setChangeUser(account);
        cmdbChangeLogRepository.save(log);
        cmdbMemoryDetailRepository.save(cmdbMemoryDetail);
        return cmdbMemoryDetail;
    }

    private void checkUnique(CmdbMemoryDetail cmdbMemoryDetail, int addOrUpdateFlag, String cmdbConfirm) {
        if (StrUtil.isNotEmpty(cmdbMemoryDetail.getSn())){
            if (addOrUpdateFlag == 1){
                findSame(cmdbMemoryDetail,cmdbConfirm);
            } else {
                //修改情况，要把已有结果查询出来，如果有变化还要校验
                Optional<CmdbMemoryDetail> result = cmdbMemoryDetailRepository.findById(cmdbMemoryDetail.getMemoryDetailId());
                if (result.isPresent()){
                    if (result.get().getSn() != null && ! result.get().getSn().equals(cmdbMemoryDetail.getSn())){
                        if (result.get().getIsDelete().equals(NO_DELETE)){
                            findSame(cmdbMemoryDetail,cmdbConfirm);
                        }
                    }
                    //修改情况存在未删除的记录
                } else {
                    findSame(cmdbMemoryDetail,cmdbConfirm);
                }
            }

        }
    }

    public void findSame(CmdbMemoryDetail cmdbMemoryDetail, String cmdbConfirm) {
        List<CmdbMemoryDetail> result = cmdbMemoryDetailRepository.findAllBySnAndIsDelete(cmdbMemoryDetail.getSn(), NO_DELETE);
        if (CollectionUtil.isNotEmpty(result)){
            throw PlatformException.errorWithOutMail("序列号重复");
        }
        if (!StrUtil.equals(CMDB_CONFIRM,cmdbConfirm)){
            List<FlowFormPartIn> flowFormPartInDetails = flowFormPartInRepo.findFlowMemorySn(cmdbMemoryDetail.getSn());
            if (CollectionUtil.isNotEmpty(flowFormPartInDetails)){
                throw PlatformException.errorWithOutMail("有发起过的流程"+flowFormPartInDetails.get(0).getProcessTitle()+"存在相同的内存序列号");
            }
        }
    }

    public void deleteMemoryDetail(CmdbMemoryDetail cmdbMemoryDetail, String account) {
        CmdbChangeLog log = new CmdbChangeLog();
        log.setChangeContent(JSONObject.toJSONString(cmdbMemoryDetail));
        log.setChangeFrom(CMDB_MEMORY_DETAIL);
        log.setChangeId(cmdbMemoryDetail.getMemoryDetailId().toString());
        log.setChangeUser(account);
        log.setChangeType(DELETE_STRING);
        Optional<CmdbMemoryDetail> optional = cmdbMemoryDetailRepository.findById(cmdbMemoryDetail.getMemoryDetailId().intValue());
        if (optional.isPresent()) {
            CmdbMemoryDetail bean = optional.get();
            bean.setIsDelete(DELETED);
            cmdbMemoryDetailRepository.save(bean);
            cmdbChangeLogRepository.save(log);
        } else {
            throw PlatformException.errorWithOutMail("删除记录不存在");
        }
    }

    public void deleteByCodeList(List<String> codes, String account) {
        CmdbChangeLog log = new CmdbChangeLog();
        log.setChangeContent(JSONObject.toJSONString(codes));
        log.setChangeFrom(CMDB_MEMORY_DETAIL);
        log.setChangeUser(account);
        log.setChangeType(DELETE_BATCH_STRING);
        cmdbChangeLogRepository.save(log);
        cmdbMemoryDetailRepository.updateIsDeleteByCodes(DELETED,codes);

    }

    public void deleteByDeviceDetailId(Integer deviceDetailId, String operator) {
        CmdbChangeLog log = new CmdbChangeLog();
        log.setChangeContent(JSONObject.toJSONString(deviceDetailId));
        log.setChangeFrom(CMDB_DEVICE_DETAIL);
        log.setChangeUser(operator);
        log.setChangeType(DELETE_BATCH_STRING);
        cmdbChangeLogRepository.save(log);
        cmdbMemoryDetailRepository.updateIsDeleteByDeviceDetailId(DELETED, deviceDetailId);
    }

    public void outByDeviceDetail(CmdbDeviceDetail h, String operator) {
        List<CmdbMemoryDetail> memoryDetails = cmdbMemoryDetailRepository.findAllByDeviceCodeAndIsDelete(h.getDeviceDetailCode(), NO_DELETED);
        memoryDetails.stream().forEach(e -> e.setLifeStatus(PART_LIFE_CYCLE_OUT));
        cmdbMemoryDetailRepository.saveAll(memoryDetails);
        CmdbChangeLog log = new CmdbChangeLog();
        log.setChangeContent(JSONObject.toJSONString(h.getDeviceDetailId()));
        log.setChangeFrom(CMDB_DEVICE_DETAIL);
        log.setChangeUser(operator);
        log.setChangeType(UPDATE_STRING);
        cmdbChangeLogRepository.save(log);
    }

    public void outBySn(String sn, String operator) {
        List<CmdbMemoryDetail> memoryDetails = cmdbMemoryDetailRepository.findAllBySnAndIsDelete(sn,NO_DELETED);
        CmdbMemoryDetail memoryDetail = memoryDetails.get(0);
        memoryDetail.setLifeStatus(PART_LIFE_CYCLE_OUT);
        cmdbMemoryDetailRepository.save(memoryDetail);
        CmdbChangeLog log = new CmdbChangeLog();
        log.setChangeContent(JSONObject.toJSONString(sn));
        log.setChangeFrom(CMDB_MEMORY_DETAIL);
        log.setChangeUser(operator);
        log.setChangeType(UPDATE_STRING);
        cmdbChangeLogRepository.save(log);
    }


    /**
     * 根据序列号查询
     * @param snList
     * @return
     */
    public List<CmdbMemoryDetail> listBySn(List<String> snList) {
        Map<String, Object> param = new HashMap<>();
        param.put("INSTR_sn", StringUtils.join(snList, ","));
        param.put("EQ_isDelete", 0);

        List<CmdbMemoryDetail> detailLis = cmdbMemoryDetailRepository.findAll(SpecificationUtil.buildSpecification(param, CmdbMemoryDetail.class));
        return detailLis;
    }

    public List<CmdbMemoryDetail> listByDetailCode(List<String> collect) {
        return cmdbMemoryDetailRepository.findAllByMemoryDetailCodeIn(collect);
    }
}
